import * as THREE from "../../three/build/three.module.js";
import {OrbitControls} from "../../three/examples/jsm/controls/OrbitControls.js";
import {MapControls} from "../../three/examples/jsm/controls/MapControls.js";
import {DragControls} from "../../three/examples/jsm/controls/DragControls.js";
import {TransformControls} from "../../three/examples/jsm/controls/TransformControls.js";
import {MyMap, AreaData, UI} from "./myclass.js";
import {AnimateEvents} from "./animateevents.js";

let scene, camera, renderer, raycaster;
let areaDatas={};
window.areaDatas = areaDatas;
MyMap.areaDatas = areaDatas;
window.THREE = THREE;


init();
animate();
UI.CreateUI();
UI.CreateUI2();


function init(){

    initThree();
    initCamera();
    initScene();
    // testScene();
    initRay();

    function initThree(){
        scene = new THREE.Scene();
        camera = new THREE.PerspectiveCamera(50, window.innerWidth/ window.innerHeight, 0.01, 1000);
        renderer = new THREE.WebGLRenderer({ antialias: true, logarithmicDepthBuffer: true });
        renderer.alpha = true;
        renderer.setClearColor(0x000000,0.);
        renderer.domElement.style.background="green";
        camera.position.z = 150;

        camera.rotation.x = -Math.PI/2;

        renderer.setSize(window.innerWidth, window.innerHeight);
        document.body.appendChild(renderer.domElement);

        camera.updateMatrix();
        // updateMatrix();
        let control = new MapControls(camera, renderer.domElement);
        window.control = control;
        control.minPolarAngle = 0;
        control.maxPolarAngle = Math.PI/3;

        window.scene = scene;
        window.camera = camera;
        window.renderer = renderer;
    }

    function initCamera(){
        camera.position.set(121.47932044988366,1.1891344262760652,-31.20926404289787);
        control.target.set( 121.47932044988366,0                 ,-31.20926404289787);
        control.update();
    }

    function initScene(){
        initShangHai();
    }

    function initShangHai(){

        $.getJSON("./上海市.json", function (data) {
            let shanghaiMesh = new THREE.Group();

            for(let featureI=0; featureI<data.features.length; featureI++){ // 每个区 featureI featureIndex
                let feature = data.features[featureI];
                let areaData = new AreaData(feature.properties);
                let material = MyMap.materialDefault();
                let materialLineTop = MyMap.materialLineTop();

                console.log(areaData.name);
                areaDatas[areaData.name] = areaData;
                areaData.setMesh(new THREE.Group(), new THREE.Group());
                shanghaiMesh.add(areaData.mesh, areaData.lineMesh);


                for(let shapeI=0; shapeI<feature.geometry.coordinates.length; shapeI++){ // 每个连续的,不分离的形状
                    let shapeData = feature.geometry.coordinates[shapeI];

                    for(let carveI=0; carveI<shapeData.length; carveI++){ // 每个子午线切割后的形状

                        let carveData = shapeData[carveI];
                        let shape = new THREE.Shape();
                        shape.moveTo(...carveData[carveData.length-1]);

                        for(let i=0; i< carveData.length; i++){ // 每个坐标
                            shape.lineTo(...carveData[i]);
                        }

                        areaData.mesh.add(createShape(shape,material));
                        areaData.lineMesh.add(createLine(shape,materialLineTop));

                    }

                }

                areaData.Height = 0.2;
                    
            }

            let shanghaiBox = new THREE.Group();
            shanghaiBox.add(shanghaiMesh);
            shanghaiBox.rotation.x = -Math.PI/2;
            // shanghaiBox.position.set(-121, -31);

            scene.add(shanghaiBox);

            initShangHaiDescribe();
        });    

    }

    function initShangHaiDescribe(){
        $.getJSON("./上海市各区描述.json", function (data) {
            console.log(`data`,data);
            for(let key in areaDatas){
                areaDatas[key].describe = data[`数据`][key];
                areaDatas[key].describeUnit = data[`单位`];
            }
        });
    }

    function createShape(shape, material){
        // TODO: 完善
        // let geometry = new THREE.ShapeGeometry(shape);
        let extrudeSettings = { depth: 1 , bevelEnabled: false }
        let geometry = new THREE.ExtrudeBufferGeometry( shape, extrudeSettings );

        // let material = new THREE.MeshBasicMaterial({color:0xff0000, depthTest:true, depthWrite:true});
        let mesh = new THREE.Mesh(geometry, material);
        return mesh;
    }

    function createLine(shape,materialLineTop){
        shape.autoClose = true;
        var points = shape.getPoints();
        var geometryPoints = new THREE.BufferGeometry().setFromPoints( points );
        var lineBottom = new THREE.Line( geometryPoints, MyMap.materialLineBottom );
        var lineTop = new THREE.Line( geometryPoints, materialLineTop);
        lineBottom.position.z = -0.0001;
        lineTop.position.z = 1.0001;

        let lines = new THREE.Group();
        lines.add(lineBottom, lineTop);
        return lines;
    }
    // TODO: DELETE test
    function testScene(){
        let mesh = new THREE.Mesh(
            new THREE.BoxBufferGeometry(),
            new THREE.MeshBasicMaterial({color: 0xff0000})
        );
        mesh.position.set(121.49,0,-31.22);
        scene.add(mesh);

        // mesh = new THREE.Mesh(
        //     new THREE.BoxBufferGeometry(),
        //     new THREE.MeshBasicMaterial({color: 0x00ff00})
        // );
        // mesh.position.y=5;
        // scene.add(mesh);

        // mesh = new THREE.Mesh(
        //     new THREE.BoxBufferGeometry(),
        //     new THREE.MeshBasicMaterial({color: 0x0000ff})
        // );
        // mesh.position.z=5;
        // scene.add(mesh);
    }

    function initRay(){
        raycaster = new THREE.Raycaster();
        let mouseDownPosition = new THREE.Vector2();
        let isMouseMoveAfterDown = false;

        function getMousePos(e){ // 发生射线需要的位置, e为鼠标事件
            let mousePos = new THREE.Vector3();
            let rendererSize=renderer.getSize();
            mousePos.set(e.offsetX/rendererSize.x-.5, -(e.offsetY/rendererSize.y-.5));
            mousePos.x *= 2;
            mousePos.y *= 2;
            return mousePos;
        }

        renderer.domElement.addEventListener(`mousedown` , function(e){
            if(e.button != 0) return; // 如果不是左击, 直接跳出
            mouseDownPosition.set(e.offsetX,e.offsetY); // 记录鼠标按下时的坐标
            isMouseMoveAfterDown = false;
        });

        
        renderer.domElement.addEventListener(`mouseup` , function(e){
            if(e.button != 0) return; // 如果不是左击, 直接跳出
            if(isMouseMoveAfterDown == true) return; // 是否移过位置,移动过,跳出
            rayLaunch(e);

            function rayLaunch(e){
                let mousePos = getMousePos(e);
                let items = []; // 可以点击/受射线影响的对象
                for(let key in areaDatas ){
                    items.push(...areaDatas[key].mesh.children);
                }
                raycaster.setFromCamera(mousePos, camera);
                let intersection = raycaster.intersectObjects(items);

                if(intersection.length){
                    let areaData = intersection[0].object.parent.data;
                    MyMap.Click(areaData);
                }else{
                    MyMap.Click(null);
                }
            }
        });

        renderer.domElement.addEventListener(`mousemove` , function(e){
            if(mouseDownPosition.x != e.offsetX || mouseDownPosition.y != e.offsetY) // 判断鼠标按下后是否移动过
                isMouseMoveAfterDown = true;
            

            rayLaunch(e);

            function rayLaunch(e){
                let mousePos = getMousePos(e);
                let items = [];
                
                for(let key in areaDatas ){
                    items.push(...areaDatas[key].mesh.children);
                }
                
                raycaster.setFromCamera(mousePos, camera);
                let intersection = raycaster.intersectObjects(items);

                if(intersection.length){
                    let areaData = intersection[0].object.parent.data;
                    MyMap.MouseHover(areaData);
                }else{
                    MyMap.MouseHover(null);
                }
            }
            
        });

    }


}



function animate(){
    requestAnimationFrame(animate);
    AnimateEvents.Run();
    renderer.render(scene, camera);
}

